#include<iostream>
#include<functional>
#include<memory>
#include<vector>
#include<unordered_map>
#include<cstdint>
#include<unistd.h>
using FuncTask=std::function<void()>;
using ReleaseFunc=std::function<void()>;
class TimerTask
{
private:
    uint64_t _id;//定时器任务的对象编号
    uint32_t _timeout;//定时器超时时间
    bool _cancel;
    FuncTask _task_cb;//定时器要执行的任务
    ReleaseFunc _rf;//用来删除定时任务
public:
    TimerTask(uint64_t id,uint32_t timeset,FuncTask cb):_id(id), _timeout(timeset), _task_cb(cb),_cancel(false) {}
    ~TimerTask(){if(_cancel==false)  _task_cb();  _rf();}
    void SetRealse(ReleaseFunc cb){_rf=cb;}
    void Cancel(){_cancel=true;}
    uint32_t DelayTime(){return _timeout;}
};

class TimerWheel
{
private:
    using WeakTask=std::weak_ptr<TimerTask>;
    using PtrTask=std::shared_ptr<TimerTask>;
    int _tick;//指针，指到哪里哪里执行任务
    int _capacity;//表盘最大数量，最大延迟时间
    std::vector<std::vector<PtrTask>> _wheel;
    std::unordered_map<uint64_t,WeakTask> _timers;
private:
    void RemoveTimer(uint64_t id)
    {
        auto it=_timers.find(id);
        if(it!=_timers.end())
        {
            _timers.erase(it);
        }
    }
public:
    TimerWheel():_capacity(60),_tick(0),_wheel(_capacity){}

    void TimerAdd(uint64_t id,uint32_t delay,FuncTask cb)//新增定时任务
    {
        PtrTask pt=std::make_shared<TimerTask>(id,delay,cb);
        pt->SetRealse(std::bind(&TimerWheel::RemoveTimer,this,id));
        _timers[id]=WeakTask(pt);
        int pos=(_tick+pt->DelayTime())%_capacity;
        _wheel[pos].push_back(pt);
    };
    void TimerRefresh(uint64_t id)//刷新定时任务，当有新连接到来,通过weakptr找到对应id生成一个shared令count++;
    {
        auto it=_timers.find(id);
        if(it==_timers.end()){return;}
        PtrTask pt=it->second.lock();//获取对应weak的shared
        int pos=(_tick+pt->DelayTime())%_capacity;
        _wheel[pos].push_back(pt);
    };

    void RunTimerTask()
    {
        _tick=(_tick+1)%_capacity;
        _wheel[_tick].clear();//清空当前表盘刻度下的shared，自动执行析构函数
    }

    void TimerCancel(uint64_t id)
    {
        auto it=_timers.find(id);
        if(it==_timers.end()){return;}
        PtrTask pt=it->second.lock();
        if(pt) pt->Cancel();
    }
};


class Test {
    public:
        Test() {std::cout << "构造" << std::endl;}
        ~Test() {std::cout << "析构" << std::endl;}
};

void DelTest(Test *t) {
    delete t;
}

int main()
{
    TimerWheel tw;

    Test *t = new Test();

    tw.TimerAdd(888, 5, std::bind(DelTest, t));

    for(int i = 0; i < 5; i++) {
        sleep(1);
        tw.TimerRefresh(888);//刷新定时任务
        tw.RunTimerTask();//向后移动秒针
        std::cout << "刷新了一下定时任务，重新需要5s中后才会销毁\n";
    }
    
    tw.TimerCancel(888);
    while(1) {
        sleep(1);
        std::cout << "111-------------------\n";
        tw.RunTimerTask();//向后移动秒针
    }
    return 0;
}
